﻿using FastBuild;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using Wechat_PublicNumber.Model;
using Wechat_PublicNumber.SettingModel;

namespace Wechat_PublicNumber.Common
{
    /// <summary>
    /// 三方接口调用
    /// </summary>
    [Injection(DIPattern.Singleton)]
    public class CommonHttpInvoke
    {
        [Autowired]
        private HttpClinetHelper _clinetHelper;

        [Autowired]
        private ILog _logger;

        [Autowired]
        private CommonHttpSetting _config;

        [Autowired]
        private IMemoryCache _cache;

        [Autowired]
        private IHttpClientFactory _httpClientFactory;

        /// <summary>
        /// Gould 根据经纬度获取位置信息
        /// </summary>
        /// <returns></returns>
        public async Task<GouldAddressRespone> GetAddressByLongitude_Latitude(string longitude, string latitude)
        {
            //经纬度获取地址
            var responeData = await _clinetHelper.JsonGet<GouldAddressRespone>($"{_config.GouldBaseUrl}/geocode/regeo?key={_config.GouldKey}&location={longitude},{latitude}&extensions=base&batch=false");
            if (responeData.status == 0)
                return null;

            return responeData;
        }

        /// <summary>
        /// Gould 根据区域编码获取天气
        /// </summary>
        /// <param name="cityCode"></param>
        /// <param name="type">base:返回实况天气 all:返回预报天气</param>
        /// <returns></returns>
        public async Task<GouldWeatherRespone> GetGouldWeatherInfoByAreaCode(string cityCode, string type = "base")
        {
            //根据区域编码获取天气
            var responeData = await _clinetHelper.JsonGet<GouldWeatherRespone>($"{_config.GouldBaseUrl}/weather/weatherInfo?key={_config.GouldKey}&city={cityCode}&extensions={type}");
            if (responeData.status == 0)
                return null;

            return responeData;
        }

        /// <summary>
        /// TianAPI 根据区域编码获取天气
        /// </summary>
        /// <param name="city"></param>
        /// <returns></returns>
        public async Task<TianWeatherRespone> GetTianWeatherInfoByAreaCode(string city)
        {
            //根据区域编码获取天气
            var responeData = await _clinetHelper.JsonGet<TianWeatherRespone>($"{_config.TianBaseUrl}/tianqi/index?key={_config.TianKey}&city={city}&type=1");
            if (responeData.code != 200)
                return null;

            return responeData;
        }

        /// <summary>
        /// XueQiu 下载雪球的一个股票详情页面
        /// </summary>
        /// <param name="stockCode"></param>
        /// <returns></returns>
        public async Task<string> DownloadXueQiuOneStockPage(string stockCode)
        {
            if (string.IsNullOrEmpty(stockCode))
                throw new Exception("stockCode can not Empty");

            using (var client = _httpClientFactory.CreateClient())
            {
                using (HttpResponseMessage response = await client.GetAsync($"{_config.XueQiuBaseUrl}/S/{stockCode}"))
                {
                    using (HttpContent content = response.Content)
                    {
                        var returnPageData = await content.ReadAsStringAsync();

                        var regexMatch = Regex.Match(returnPageData, "hm.js\\?[0-9a-z]+");
                        var id = regexMatch.Value.Split("?")[1];

                        //设置cookie
                        var allcookie = response.Headers.GetValues("Set-Cookie").Select(s => s.Split(";")[0]).ToList();
                        allcookie.Add($"Hm_lvt_{id}={new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}");
                        allcookie.Add($"Hm_lpvt_{id}={new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}");
                        var cookie = string.Join("; ", allcookie);
                        if (!string.IsNullOrEmpty(cookie))
                            _cache.Set("PushStockJobCookie", cookie, TimeSpan.FromDays(1));
                        return returnPageData;
                    }
                }
            }
        }

        /// <summary>
        /// XueQiu 获取股票实时信息
        /// </summary>
        /// <param name="stockCode"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task<string> GetRealTimeStock(string stockCode)
        {
            if (string.IsNullOrEmpty(stockCode))
                throw new Exception("stockCode can not Empty");

            return await XueqiuHttpGet($"{_config.XueQiuStockBaseUrl}/v5/stock/realtime/quotec.json?symbol={stockCode}", stockCode);
        }

        /// <summary>
        /// XueQiu 搜索股票信息
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public async Task<List<GetStockInfoReturn>> GetStockInfo(string key)
        {
            List<GetStockInfoReturn> returnData = null;
            if (string.IsNullOrEmpty(key))
                throw new Exception("stockCode can not Empty");

            var returnString = await XueqiuHttpGet($"{_config.XueQiuBaseUrl}/query/v1/suggest_stock.json?q={System.Web.HttpUtility.UrlDecode(key, Encoding.UTF8)}");
            var searchStockList = JObject.Parse(returnString);
            if (searchStockList["data"] != null)
                returnData = JsonConvert.DeserializeObject<List<GetStockInfoReturn>>(searchStockList["data"].ToString());
            if (returnData != null)
                returnData = returnData.Where(s => s.stock_type == 11).ToList();

            return returnData;
        }

        /// <summary>
        /// 雪球网站Get请求
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private async Task<string> XueqiuHttpGet(string url, string code = "SH600111")
        {
            if (!_cache.TryGetValue("PushStockJobCookie", out var cookie))
                await DownloadXueQiuOneStockPage("SZ000630");

            using (HttpRequestMessage requestMessage = new HttpRequestMessage())
            {
                requestMessage.Method = HttpMethod.Get;
                requestMessage.RequestUri = new Uri(url);
                requestMessage.Headers.Add("Accept-Encoding", "gzip, deflate, br");
                requestMessage.Headers.Add("cookie", _cache.Get("PushStockJobCookie").ToString());
                requestMessage.Headers.Add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36");
                requestMessage.Headers.Add("referer", $"https://xueqiu.com/S/{code}");
                requestMessage.Headers.Add("origin", "https://xueqiu.com");
                requestMessage.Headers.Add("Host", "xueqiu.com");

                using (var httpclient = _httpClientFactory.CreateClient("GetStock"))
                {
                    var stock = await httpclient.SendAsync(requestMessage);
                    var returnString = await stock.Content.ReadAsStringAsync();
                    _logger.Info($"url:{url},returnString:{returnString}", "XueqiuHttpGet");
                    return returnString;
                }
            }
        }
    }

    public class GetStockInfoReturn
    {
        public string code { get; set; }

        public string label { get; set; }

        public string query { get; set; }

        public int stock_type { get; set; }
    }
}
